-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IBX-8190: Add Symfony's Serializer support #121
base: main
Are you sure you want to change the base?
Conversation
Since I consulted this approach I'll give some explanations too. Whole concept relies on using While analyzing how So, since the primary difference between Symfony normalization and our Visitor's processing is that Symfony returns data and Visitors pass around |
b39b477
to
0ddbb6d
Compare
src/bundle/DependencyInjection/Compiler/ValueObjectVisitorResolverPass.php
Outdated
Show resolved
Hide resolved
src/contracts/Input/Parser/Query/Criterion/BaseCriterionProcessor.php
Outdated
Show resolved
Hide resolved
1ea164c
to
847a54d
Compare
src/lib/Output/Generator/InMemory/Xml/FieldTypeHashGenerator.php
Outdated
Show resolved
Hide resolved
src/lib/Output/Generator/InMemory/Xml/FieldTypeHashGenerator.php
Outdated
Show resolved
Hide resolved
src/lib/Output/Generator/InMemory/Xml/FieldTypeHashGenerator.php
Outdated
Show resolved
Hide resolved
/** | ||
* Generates a JSON object from the given $hashArray with $parent. | ||
* | ||
* @param \Ibexa\Rest\Output\Generator\Json\ArrayObject|\Ibexa\Rest\Output\Generator\Json\JsonObject $parent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Q: what is the source of that confusion here? Can we use this opportunity to clean this up instead? (as mentioned earlier)
/** @phpstan-ignore-next-line */ | ||
$object->value = []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making PHPStan ignore this won't stop a fatal error once we run on PHP version which doesn't allow dynamic properties.
20b17e6
to
1243dd6
Compare
{ | ||
use NormalizerAwareTrait; | ||
|
||
private const string CALLED_CONTEXT = __CLASS__ . '_CALLED'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alongosz we might want to standardize naming for encoder key, when it should be skipped in the next normalization pass, just like in your PR.
0d3387d
to
cc840b3
Compare
…izer` to Ibexa normalizers
e4a3721
to
bc4cc96
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
POST localhost/api/ibexa/v2/orders/orders and json body
Ibexa\Rest\Output\Normalizer\JsonSerializableNormalizer::normalize(): Return value must be of type string, array returned (500 Internal Server Error)
Fixed by 9322522 |
Quality Gate passedIssues Measures |
Related PRs:
https://github.com/ibexa/scheduler/pull/111
Description:
AdapterNormalizer
A new normalizer with low priority is implemented called
AdapterNormalizer
that handles data normalization or visiting data using the existing visitors. Currently, the visitors are prioritized over incoming (new) normalizers.Unfortunately, the problem is that in order to visit value objects the
Visitor
andGenerator
have to be created and passed as arguments toValueObjectVisitor
instance.Ibexa\Contracts\Rest\Output\ValueObjectVisitorDispatcher
It is deleted now and the responsibility for finding a proper visitor is moved to the newly introduced
ValueObjectVisitorResolverInterface
.Ibexa\Contracts\Rest\OutputVisitor
The
visitValueObject
method has to behave exactly the same as before as it's used throughout the app so we should keep BC here. I don't think we can change it to use normalizer as it uses the original Visitor's generator.Concept made by Paweł.
Documentation:
From now on the responses generated by Ibexa will be normalized and encoded by Symfony's Serializer https://symfony.com/doc/5.x/serializer.html. This is a change from the old way of doing things when the only responsibility laid on
Json\Generator
orXml\Generator
to handle things, so normalizing and encoding depending on the generator used. Currently, the generators are responsible for generatingJsonObject
which is a representation of data one wants to normalize and they allow to prepare a context for Symfony's encoder and their purpose is to keep BC for older Ibexa data structures.How a developer can take advantage of the new implementation?
Instead of writing a dedicated
ValueObjectVisitor
that handles generation ofJsonObject
insideGenerator\Xml
orGenerator\Json
(for example https://github.com/ibexa/rest/blob/main/src/lib/Server/Output/ValueObjectVisitor/Author.php) one can write a dedicated normalizer: https://symfony.com/doc/5.x/components/serializer.html#component-serializer-normalizers. Example:Imagine we have a new data structure:
TestDataObject
with the following definition:One can notice the
Location
object which in fact is an instance of Ibexa's Location, it hints that Symfony's Serializer will be able to work with such data. Instead of writing a dedicatedValueObjectVisitor
one can introduce a normalizer:We can notice how easy it is to normalize Ibexa's Location object, one simply does:
and because of how internal Ibexa's
AdapterNormalizer
works it will provide already normalized data that will be normalized using backwards-compatible value object visitors. This is really important and powerful mechanism as we are allowed to normalize both old data that use value object visitors and new data that don't have value object visitors but have dedicated normalizers instead together.Finally, to obtain the final encoded data in json/xml format from PHP object representation it really comes down to:
Symfony's Serializer will work internally with Ibexa's Generators and Value Object Visitors to normalize and encode data for the specific format (
json
in case of the above example) - the final result can be previewed here: https://github.com/ibexa/rest/blob/23bb684b4dd9d68ec5537d5fd125ebdaf26a983b/tests/integration/Serializer/_snapshot/TestDataObject.json.One must remember that normalizers that normalize Ibexa's data objects has to be registered with the following tag:
It is important for the app safety and performance to NOT autoconfigure these normalizers. If autoconfigured those will receive
serializer.normalizer
tags and will be injected into the main application serializer, which is ill-advised.QA:
Technically speaking nothing for the end-user should change, app should behave the same as before. It's definitely worth checking how REST endpoints behave with this implementation (including Scheduler ones) + testing some test data using normalizer as shown in the description above.